package cn.daniellee.plugin.wl.core;

import cn.daniellee.plugin.wl.WorldLimiter;
import cn.daniellee.plugin.wl.model.LimitWorld;
import org.apache.commons.lang.StringUtils;
import org.bukkit.Bukkit;
import org.bukkit.configuration.ConfigurationSection;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class LimitCore {

    public static String spawnWorld;

    public static List<LimitWorld> limitWorlds = new ArrayList<>();

    public static Map<String, Integer> tempOpenSecond = new ConcurrentHashMap<>();

    public void load() {
        spawnWorld = WorldLimiter.getInstance().getConfig().getString("setting.spawn-world", "world");
        if (Bukkit.getWorld(spawnWorld) == null) {
            spawnWorld = Bukkit.getWorlds().get(0).getName();
            WorldLimiter.getInstance().getLogger().info("[WorldLimiter]Spawn world not found, automatically set to the first world.");
        }
        // 更新受限的世界
        limitWorlds.clear();
        ConfigurationSection section = WorldLimiter.getInstance().getConfig().getConfigurationSection("limit-world");
        if (section != null) {
            for (String worldName : section.getKeys(false)) {
                if (worldName.equals(spawnWorld)) continue;
                LimitWorld limitWorld = new LimitWorld();
                limitWorld.setWorldName(worldName);
                limitWorld.setWorldAlias(WorldLimiter.getInstance().getConfig().getString("limit-world." + worldName + ".world-alias", worldName));
                limitWorld.setWayOfEntry(WorldLimiter.getInstance().getConfig().getString("limit-world." + worldName + ".way-of-entry", ""));
                limitWorld.setAllowEnterInterval(new ArrayList<>(WorldLimiter.getInstance().getConfig().getStringList("limit-world." + worldName + ".allow-enter-interval")));
                limitWorld.setBypassPermission(WorldLimiter.getInstance().getConfig().getString("limit-world." + worldName + ".bypass-permission", "worldlimiter.bypass." + worldName));
                limitWorld.setIgnoreCarrier(WorldLimiter.getInstance().getConfig().getBoolean("limit-world." + worldName + ".ignore-carrier", false));
                limitWorld.setProhibitedItems(new ArrayList<>(WorldLimiter.getInstance().getConfig().getStringList("limit-world." + worldName + ".prohibited-items")));
                limitWorlds.add(limitWorld);
            }
        }
    }

    public static LimitWorld getLimitWorldByName(String name) {
        return limitWorlds.stream().filter(item -> item.getWorldName().equals(name)).findFirst().orElse(null);
    }

    public static boolean checkCantEnter(Player player, LimitWorld limitWorld) {
        if (player.isOp()) return false;
        if (player.hasPermission(limitWorld.getBypassPermission()) && limitWorld.isIgnoreCarrier()) return false;
        // 首先检查背包物品
        Set<String> checkedOutItems = checkInventory(player, limitWorld);
        if (!checkedOutItems.isEmpty()) {
            player.sendMessage((WorldLimiter.getInstance().getPrefix() + WorldLimiter.getInstance().getConfig().getString("message.cant-carry", "&eIt is forbidden to bring the following items into the world: &r") + StringUtils.join(checkedOutItems, ", ")).replace("&", "§"));
            return true;
        }
        // 检查时间限制
        if (player.hasPermission(limitWorld.getBypassPermission())) return false;
        // 如果还在临时开启中
        if (getRemainingSecond(limitWorld) == 0) {
            if (limitWorld.getAllowEnterInterval().isEmpty()) {
                player.sendMessage((WorldLimiter.getInstance().getPrefix() + WorldLimiter.getInstance().getConfig().getString("message.no-interval", "&eTarget world has not set open time.")).replace("&", "§"));
            } else {
                player.sendMessage((WorldLimiter.getInstance().getPrefix() + WorldLimiter.getInstance().getConfig().getString("message.not-opening", "&eTarget world is only open at &b{interval}").replace("{interval}", StringUtils.join(limitWorld.getAllowEnterInterval(), ", "))).replace("&", "§"));
            }
            return true;
        }
        return false;
    }

    public static Set<String> checkInventory(Player player, LimitWorld limitWorld) {
        Set<String> checkedOutItems = new HashSet<>();
        List<String> prohibitedItems = limitWorld.getProhibitedItems();
        for (ItemStack itemStack : player.getInventory().getContents()) {
            if (itemStack != null) {
                String itemType = itemStack.getType().toString();
                if (prohibitedItems.contains(itemType)) {
                    checkedOutItems.add(itemType);
                }
            }
        }
        return checkedOutItems;
    }

    public static int getRemainingSecond(LimitWorld limitWorld) {
        Integer tempLeft = tempOpenSecond.get(limitWorld.getWorldName());
        if (tempLeft != null) return tempLeft;
        for (String interval : limitWorld.getAllowEnterInterval()) {
            SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
            String date = format.format(new Date());
            String startTimeStr = date + " " + interval.substring(0, 5) + ":00";
            String endTimeStr = date + " " + interval.substring(6) + ":00";
            try {
                format.applyPattern("yyyy-MM-dd HH:mm:ss");
                long startTime = format.parse(startTimeStr).getTime();
                long endTime = format.parse(endTimeStr).getTime();
                // 如果起止时间相同视为无效记录
                if (startTime == endTime) continue;
                // 如果开始时间大于结束时间，就把结束时间调整到第二天
                else if (startTime > endTime) endTime += 86400000L;
                long now = System.currentTimeMillis();
                if (now >= startTime && now < endTime) {
                    return (int) ((endTime - now) / 1000);
                }
            } catch (ParseException e) {
                e.printStackTrace();
                WorldLimiter.getInstance().getLogger().info("[WorldLimiter]Date format error.");
            }
        }
        return 0;
    }

}
